package com.smile.cloud.admin.internalFuntionInterface;

import com.smile.cloud.common.model.User;
import lombok.extern.slf4j.Slf4j;

import java.util.*;
import java.util.function.*;
import java.util.stream.Collectors;

/**
 * @author smile
 * @version V1.0
 * @className FunctionInterfaceTest
 * @description FunctionInterfaceTest
 * @date 2021/6/3
 **/
@Slf4j
public class InternalFunctionInterfaceTest {
    /**
     * 有返回值（有参）： Predicate（返回布尔值），Function(一个入参) BiFunction（两个入参） BinaryOperator（两个入参和返回值类型一致）
     * 无返回值（有参）：Consumer(一个入参) BiConsumer(两个入参)
     * 有返回值（无参）：Supplier
     */

    public static void main(String[] args) {
        List<Integer> integers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8);
        Map<Integer, String> map = new HashMap<>();
        map.put(1, "张三");
        map.put(2, "李四");
//        predicateTest1(integers);
//        functionTest1(integers);
//        consumerTest1(integers, map);
//        supplierTest1();
        comparatorTest1(integers);
    }

    private static void predicateTest1(List<Integer> integers) {
//        Predicate<Integer> predicate = new Predicate<Integer>() {
//            @Override
//            public boolean test(Integer integer) {
//                return integer > 3;
//            }
//        };
//        Predicate<Integer> predicate2 = integer -> {
//            return integer > 3;
//        };
        Predicate<Integer> predicate3 = integer -> integer > 3;

        List<Integer> collect1 = integers.stream().filter(predicate3).collect(Collectors.toList());
        log.info("predicate.test(),{}", collect1);

        Predicate<Integer> predicate4 = integer -> integer > 6;

        List<Integer> collect2 = integers.stream().filter(predicate3.and(predicate4)).collect(Collectors.toList());
        log.info("predicate.and() 交集,{}", collect2);

        List<Integer> collect3 = integers.stream().filter(predicate3.or(predicate4)).collect(Collectors.toList());
        log.info("predicate.or() 并集,{}", collect3);

        List<Integer> collect4 = integers.stream().filter(predicate3.negate()).collect(Collectors.toList());
        log.info("predicate.negate() 取反,{}", collect4);


        List<Integer> collect5 = integers.stream().filter(Predicate.isEqual(1)).collect(Collectors.toList());
        log.info("Predicate.isEqual() 对传入值是否相等,{}", collect5);
    }


    private static void functionTest1(List<Integer> integers) {

//        Function<Integer, Long> function1 = new Function<Integer, Long>() {
//            @Override
//            public Long apply(Integer integer) {
//                return (long) (integer + 10);
//            }
//        };
//
//        Function<Integer, Long> function2 = integer -> {
//            return (long) (integer + 10);
//        };
        Function<Integer, Integer> function3 = integer -> (integer + 10);

        List<Integer> collect1 = integers.stream().map(function3).collect(Collectors.toList());
        log.info("function.apply(),{}", collect1);

        Function<Integer, Integer> function4 = integer -> (integer * 10);

        List<Integer> collect2 = integers.stream().map(function3.compose(function4)).collect(Collectors.toList());
        log.info("function.compose() 先执行里面再外面,{}", collect2);

        List<Integer> collect3 = integers.stream().map(function3.andThen(function4)).collect(Collectors.toList());
        log.info("function.andThen() 先执行外面再里面,{}", collect3);

        List<Integer> collect4 = integers.stream().map(Function.identity()).collect(Collectors.toList());

        log.info("function.identity() 输入和输出一样的表达式,{}", collect4);

        BiFunction<Integer, Integer, Long> biFunction = (integer, integer2) -> (long) integer * integer2;
        log.info("biFunction.apply(),{}", biFunction.apply(1, 2));
        Function<Long, Long> function5 = (a) -> a * 10;
        log.info("biFunction.andThen(),{}", biFunction.andThen(function5).apply(1, 2));
        BinaryOperator<Integer> binaryOperator = (integer, integer2) -> integer * integer2;
        log.info("binaryOperator.apply(),{}", binaryOperator.apply(1, 2));
//        BinaryOperator.minBy(Comparator.comparing(function5))
//        log.info("binaryOperator.apply(),{}", binaryOperator(1, 2));
    }


    private static void consumerTest1(List<Integer> integers, Map<Integer, String> map) {
//        Consumer<Integer> consumer1 = new Consumer<Integer>() {
//            @Override
//            public void accept(Integer integer) {
//                log.info("consumer.accept(),{}", integer)
//            }
//        };
//
//        Consumer<Integer> consumer2 = integer -> {
//           log.info("consumer.accept(),{}", integer);
//        };
        Consumer<Integer> consumer3 = integer -> log.info("consumer.accept(),{}", integer);
        Consumer<Integer> consumer31 = integer -> log.info("consumer.accept2(),{}", integer);
//        consumer3.accept(1);
//        consumer3.andThen(consumer31).accept(1);
        integers.forEach(consumer3);

        BiConsumer<Integer, Integer> biConsumer1 = (integer, integer2) -> log.info("biConsumer.accept(),{}", integer + integer2);
        biConsumer1.accept(1, 1);

        BiConsumer<Integer, String> biConsumer2 = (a, b) -> {
            log.info("biConsumer map.forEach(),key:{},value:{}", a, b);
        };

        map.forEach(biConsumer2);

    }


    private static void supplierTest1() {
//        Supplier<User> supplier1 = new Supplier<User>() {
//            @Override
//            public User get() {
//                return User.builder().id(1).name("zhansan").build();
//            }
//        };
//        Supplier<User> supplier2 = () -> {
//            return User.builder().id(1).name("zhansan").build();
//        };
        Supplier<User> supplier3 = () -> User.builder().id(1).name("zhansan").build();

        log.info("supplier.get() 惰性构造（需要用的时候生成）,{}", supplier3.get());

    }


    private static void comparatorTest1(List<Integer> integers) {
        for (int i = 0; i < 9; i++) {
            Optional<Integer> any = integers.stream().findAny();
            log.info("stream 随机查找，{}", integers.stream().findAny().get());
        }
        integers.sort((Integer o1, Integer o2) -> o2 - o1);
        integers.forEach((i) -> log.info("list sort comparator. {}", i));
        Optional<Integer> optional = integers.stream().findFirst();



    }

}
